//
//  ChatLabel.m
//  JiaoX
//
//  Created by yinqy on 15/4/1.
//  Copyright (c) 2015年 北京娇羞科技有限公司. All rights reserved.
//

#import "ChatLabel.h"
#import <CoreText/CoreText.h>
#import "RegexKitLite.h"
#import "EmotionUtil.h"

#define kLineHeight                SCALEX(22)
#define kFaceSize                  SCALEX(22)
#define CONTENT_LEBAL_FONT SCALEX(15)


@interface ChatLabel()
{
    NSMutableAttributedString *_chatAttributedString;
}
@property(nonatomic,strong) NSMutableDictionary *images;

@end
@implementation ChatLabel

static NSString* kRegexEmotion = @"\\[[a-zA-Z0-9\\u4e00-\\u9fa5]+\\]";

static void deallocCallback( void* ref ){
    
}
static CGFloat ascentCallback( void *ref ){
    return SCALEX(22);
}
static CGFloat descentCallback( void *ref ){
    return 10;
}
static CGFloat widthCallback( void* ref ){
    return SCALEX(22);
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor clearColor];
        _images = [NSMutableDictionary dictionary];
    }
    return self;
}

- (void)drawRect:(CGRect)rect
{
    [super drawRect:rect];
    
    for (UIView* subView in self.subviews) {
        if ([subView isKindOfClass:[UIImageView class]]) {
            [subView removeFromSuperview];
        }
    }
    
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    CGContextTranslateCTM(context, 0, self.bounds.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    
    if (_chatAttributedString && _chatAttributedString.length > 0) {
        
        float currentHeight = self.bounds.size.height;
        CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedString((__bridge CFAttributedStringRef)_chatAttributedString);
        CFIndex start = 0;
        double width = self.bounds.size.width;
        
        while (currentHeight > SCALEX(5)) {
            
            currentHeight -= kLineHeight;
            
            CFIndex count = CTTypesetterSuggestClusterBreak(typesetter, start, width);
            
            CTLineRef line = CTTypesetterCreateLine(typesetter, CFRangeMake(start, count));
            CGContextSetTextPosition(context, 0, currentHeight);
            CTLineDraw(line, context);
            
            for (id runObj in (__bridge NSArray *)CTLineGetGlyphRuns(line)) {
                CTRunRef run = (__bridge CTRunRef)runObj;
                CFRange runRange = CTRunGetStringRange(run);
                
                int l = runRange.location;
                while (l < (runRange.location + runRange.length)) {
                    NSMutableDictionary* dic = [_images objectForKey:[NSString stringWithFormat:@"%d",l]];
                    if (dic) {
                        CGFloat x = CTLineGetOffsetForStringIndex(line, l, nil);
                        [dic setObject:[NSString stringWithFormat:@"%f",x] forKey:@"faceX"];
                        [dic setObject:[NSString stringWithFormat:@"%f",currentHeight] forKey:@"faceY"];
                    }
                    l++;
                }
            }
            CFRelease(line);
            start += count;
        }
        CFRelease(typesetter);
        for (NSDictionary* dictionary in _images.objectEnumerator) {
            NSString* imageName = [dictionary objectForKey:@"faceImage"];
            UIImageView* gifView = [[UIImageView alloc] init];
            [gifView setImage:IMG(imageName)];
            float mirrowY = self.bounds.size.height - [[dictionary objectForKey:@"faceY"] floatValue] - kLineHeight+SCALEX(5);
            gifView.frame = CGRectMake([[dictionary objectForKey:@"faceX"] floatValue], mirrowY , kFaceSize, kFaceSize);
            [self addSubview:gifView];
        }
        
    }
}

+ (CGSize)sizeWithNoWrapContent:(NSString *)content width:(CGFloat)aWidth
{
    CGSize size = CGSizeZero;
    CGFloat height = 0.0;
    
    NSUInteger line_num = 0;
    double width = aWidth;
    
    NSMutableAttributedString* attrString = [ChatLabel attributedStringFroXMPChatLable:content];
    
    if (attrString && attrString.length > 0) {
        CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attrString);
        CFIndex start = 0;
        while (attrString.length > start) {
            CFIndex count = CTTypesetterSuggestClusterBreak(typesetter, start, width);
            
            //            if (line_num == 0 && count == attrString.length) {  //  少于一行
            CTLineRef line = CTTypesetterCreateLine(typesetter, CFRangeMake(start, count));
            float offsetX = CTLineGetOffsetForStringIndex(line, count, NULL);
            if (offsetX > size.width) {
                size.width = offsetX;
            }
            
            CFRelease(line);
            //            }
            
            start += count;
            height += kLineHeight;
            line_num ++;    // 下一行
            
        }
//        height += 5;
        CFRelease(typesetter);
    }
    
    
    //    if (line_num > 1) {
    //        size.width = aWidth;
    //    }
    
    size.height = height;
    return size;
}

+ (CGSize)sizeWithContent:(NSString *)content width:(CGFloat)aWidth
{
    content = [content replaceCharacter:@"\n" withString:@" \n"];
    // 需要把换行符号截取出来
    NSArray *aList = [content componentsSeparatedByString:@"\n"];
    if (!aList) {
        aList = [content componentsSeparatedByString:@"\r\n"];
    }
    if (!aList) {
        aList = [content componentsSeparatedByString:@"\r"];
    }
    CGSize size = CGSizeZero;
    for (NSString *aStr in aList) {
        CGSize tSize = [ChatLabel sizeWithNoWrapContent:aStr width:aWidth];
        size.height += tSize.height;
        if (tSize.width > size.width) {
            size.width = tSize.width;
        }
    }
    int sizeWidth = size.width+1;
    int sizeHeight = size.height+1;
    size.width = sizeWidth;
    size.height = sizeHeight;
    
    return size;
}


+ (NSMutableAttributedString *)attributedStringFroXMPChatLable:(NSString *)text
{
    
    if (!text) text = @"";
    CGFloat font = CONTENT_LEBAL_FONT;
    NSMutableAttributedString* attr = [[NSMutableAttributedString alloc] initWithString:text];
    if (attr) {
        CTFontRef fontRef = CTFontCreateWithName((CFStringRef)[UIFont systemFontOfSize:font].fontName, font, NULL);
        [attr addAttribute:(NSString *)kCTFontAttributeName value:(__bridge id)fontRef range:NSMakeRange(0, attr.length)];
        CFRelease(fontRef);
        
        CTRunDelegateCallbacks callbacks;
        callbacks.version = kCTRunDelegateVersion1;
        callbacks.getAscent = ascentCallback;
        callbacks.getDescent = descentCallback;
        callbacks.getWidth = widthCallback;
        callbacks.dealloc = deallocCallback;
        
        CTRunDelegateRef runDelegate = CTRunDelegateCreate(&callbacks, NULL);
        NSDictionary *attrDictionaryDelegate = [NSDictionary dictionaryWithObjectsAndKeys:
                                                (__bridge id)runDelegate, (NSString*)kCTRunDelegateAttributeName,
                                                [UIColor clearColor].CGColor,(NSString*)kCTForegroundColorAttributeName,
                                                nil];
        NSAttributedString *faceAttributedString = [[NSAttributedString alloc] initWithString:@"*" attributes:attrDictionaryDelegate];
        NSArray *array = [attr.string arrayOfCaptureComponentsMatchedByRegex:kRegexEmotion];
        for (NSArray *arr in array) {
            NSString* faceChar = [arr objectAtIndex:0];
            NSString* faceString = [[EmotionUtil sharedInstance] imageNameWithEmotionChar:faceChar];
            if (faceString) {
                NSRange range = [attr.string rangeOfString:faceChar];
                [attr replaceCharactersInRange:range withAttributedString:faceAttributedString];
            }
        }
    }
    return attr;
}

- (void)setAttributeString:(NSString *)string
{
    [_images removeAllObjects];
    if (!string) string = @"";
    CGFloat font = CONTENT_LEBAL_FONT;

    NSMutableAttributedString* attr = [[NSMutableAttributedString alloc] initWithString:string];
    if (attr) {
        
        CTFontRef fontRef = CTFontCreateWithName((CFStringRef)[UIFont systemFontOfSize:font].fontName, font, NULL);
        [attr addAttribute:(NSString *)kCTFontAttributeName value:(__bridge id)fontRef range:NSMakeRange(0, attr.length)];
        
        
        CGFloat lineSpace = 0.0f;
        CTParagraphStyleSetting lineSpaceStyle;
        lineSpaceStyle.spec = kCTParagraphStyleSpecifierLineSpacingAdjustment;
        lineSpaceStyle.valueSize = sizeof(lineSpace);
        lineSpaceStyle.value =&lineSpace;
        
        CTParagraphStyleSetting settings[] = {lineSpaceStyle};
        CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(settings, 2);
        
        [attr addAttribute:(NSString *)kCTParagraphStyleAttributeName value:(__bridge id)paragraphStyle range:NSMakeRange(0, attr.length)];
        
        
        CFRelease(fontRef);
        
        CTRunDelegateCallbacks callbacks;
        callbacks.version = kCTRunDelegateVersion1;
        callbacks.getAscent = ascentCallback;
        callbacks.getDescent = descentCallback;
        callbacks.getWidth = widthCallback;
        callbacks.dealloc = deallocCallback;
        
        CTRunDelegateRef runDelegate = CTRunDelegateCreate(&callbacks, NULL);
        NSDictionary *attrDictionaryDelegate = [NSDictionary dictionaryWithObjectsAndKeys:
                                                (__bridge id)runDelegate, (NSString*)kCTRunDelegateAttributeName,
                                                [UIColor clearColor].CGColor,(NSString*)kCTForegroundColorAttributeName,
                                                nil];
        
        NSAttributedString *faceAttributedString = [[NSAttributedString alloc] initWithString:@"*" attributes:attrDictionaryDelegate];
        
        NSArray *array = [attr.string arrayOfCaptureComponentsMatchedByRegex:kRegexEmotion];
        for (NSArray *arr in array) {
            NSString* faceChar = [arr objectAtIndex:0];
            //            NSMutableDictionary* dictionary = [NSMutableDictionary dictionaryWithObject:faceChar forKey:@"faceKey"];
            NSMutableDictionary* dictionary = [[NSMutableDictionary alloc]initWithObjects:@[faceChar] forKeys:@[@"faceKey"]];
            NSString* faceString = [[EmotionUtil sharedInstance] imageNameWithEmotionChar:faceChar];
            if (faceString) {
                NSRange range = [attr.string rangeOfString:faceChar];
                [attr replaceCharactersInRange:range withAttributedString:faceAttributedString];
                [dictionary setObject:[[EmotionUtil sharedInstance] imageNameWithEmotionChar:faceChar] forKey:@"faceImage"];
                [_images setObject:dictionary forKey:[NSString stringWithFormat:@"%lu",(unsigned long)range.location]];
            }
        }
    }
    _chatAttributedString = attr;
}

@end
